package org.overmind.ieat.server.dao.provider;


import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.overmind.ieat.server.entity.Provider;

import org.overmind.ieat.server.exceptions.DatabaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;

import java.util.List;

/**
 * @author eugene.karanda
 */
@Repository
public class ProviderDaoHibernate //TODO add log.debug methods
        implements ProviderDao {

    private static Logger logger = LoggerFactory.getLogger(ProviderDaoHibernate.class);

    @Resource
    private SessionFactory sessionFactory;

    @Override
    public List<Provider> getProviderList() throws DatabaseException {
        Session session = null;

        try {
            session = sessionFactory.openSession();

            return session.createCriteria(Provider.class).list();
        } catch (HibernateException exception) {
            throw new DatabaseException("Database exception during execute method of dao", exception);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    @Override
    public Provider findById(int id) throws DatabaseException {
        Session session = null;

        try {
            session = sessionFactory.openSession();
            return (Provider) session.createCriteria(Provider.class)
                    .add(Restrictions.eq("id", id)).uniqueResult();
        } catch (HibernateException exception) {
            logger.error("Exception during execute dao method (id = {})", id);
            throw new DatabaseException("Database exception during execute method of dao", exception);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    @Override
    public boolean deleteById(int id) throws DatabaseException {
        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            Provider provider = (Provider) session.get(Provider.class, id);

            if (provider != null) {
                transaction = session.beginTransaction();

                session.delete(provider);
                transaction.commit();
                return true;
            } else {
                return false;
            }
        } catch (HibernateException exception) {
            logger.error("Exception during execute dao method (id = {})", id);

            try {
                if(transaction != null) {
                    logger.info("Try rollback changes");
                    transaction.rollback();
                    logger.info("Rollback success");
                } else {
                    logger.warn("Can`t rollback changes: transaction not created");
                }
            } catch (HibernateException rollbackException) {
                logger.error("Couldn't rollback transaction", rollbackException);
            }

            throw new DatabaseException("Database exception during execute method of dao", exception);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    @Override
    public Integer save(Provider provider) throws DatabaseException {
        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();

            Integer providerId = (Integer) session.save(provider);
            transaction.commit();

            return providerId;
        } catch (HibernateException exception) {
            logger.error("Exception during execute dao method (provider = {})", provider);

            try {
                if(transaction != null) {
                    logger.info("Try rollback changes");
                    transaction.rollback();
                    logger.info("Rollback success");
                } else {
                    logger.warn("Can`t rollback transaction: transaction not created");
                }
            } catch (HibernateException rollbackException) {
                logger.error("Couldn't rollback transaction", rollbackException);
            }

            throw new DatabaseException("Database exception during execute method of dao", exception);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    @Override
    public Provider update(int id, Provider provider) throws DatabaseException {
        Session session = null;
        Transaction transaction = null;

        try {
            session = sessionFactory.openSession();

            Provider updateProvider = (Provider) session.get(Provider.class, id);

            if(updateProvider != null) {
                transaction = session.beginTransaction();

                updateProvider.setName(provider.getName());
                updateProvider.setDescription(provider.getDescription());
                updateProvider.setWebsite(provider.getWebsite());

                session.update(updateProvider);
                transaction.commit();

                return updateProvider;
            } else {
                return null;
            }

        } catch (HibernateException exception) {
            logger.error("Exception during execute dao method (id = {}, provider = {})", id, provider);

            try {
                if(transaction != null) {
                    logger.info("Try rollback changes");
                    transaction.rollback();
                    logger.info("Rollback success");
                } else {
                    logger.warn("Can`t rollback transaction: transaction not created");
                }
            } catch (HibernateException rollbackException) {
                logger.error("Couldn’t roll back transaction", rollbackException);
            }

            throw new DatabaseException("Database exception during execute method of dao", exception);
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}
